-
Notifications
You must be signed in to change notification settings - Fork 2.7k
feat: adds trash support (soft deletes) #12656
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
… deleteing if restricted by delete access
Feels like we should add some tests for docs that were soft deleted and then moved out of trash. Looks like
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor code cleanup, looks good otherwise.
… && throw error on restoreVersion operation for trashed docs
Required for #12656. ### What This PR introduces full admin UI support for Payload’s new soft delete (`trash`) functionality. When a collection has `trash: true`, documents can now be soft-deleted from the admin panel, viewed in a dedicated “Trash” view, and optionally restored. ### How - Trash View: Adds a new route at `/collections/:collectionSlug/trash` to view and manage soft-deleted documents. - Delete Behavior: On collections with `trash: true`, deleting a document from the admin UI will soft delete it by default (setting the `deletedAt` timestamp). A new checkbox in the delete confirmation modal allows for permanent deletion (bypassing trash) if desired. - Restore Action: Soft-deleted documents can be restored by clearing the `deletedAt` timestamp via a new “Restore” button. - Trashed Document Behavior: When viewing a trashed document, the UI renders in a fully read-only state. However, users can still navigate to the **API**, **Preview**, and **Versions** tabs from the edit view to inspect or interact with those surfaces. - Access Control Integration: All trash-related actions respect the collection’s delete access control. ### Notes - This builds on the backend soft delete support introduced in a separate PR. - UI behavior integrates cleanly with autosave, drafts, and version history. - Designed to be unobtrusive for collections that do not enable trash.
📦 esbuild Bundle Analysis for payloadThis analysis was generated by esbuild-bundle-analyzer. 🤖
Largest pathsThese visualization shows top 20 largest paths in the bundle.Meta file: packages/next/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js
Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js
Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js
DetailsNext to the size is how much the size has increased or decreased compared with the base branch of this PR.
|
This is looking amazing, great job. Once this is marked as stable I'll make sure to move my soft delete plugin into maintenance mode and point users towards this feature instead. |
Looking forward to this one! |
What?
This PR introduces complete trash (soft-delete) support. When a collection is configured with
trash: true
, documents can now be soft-deleted and restored via both the API and the admin panel.Why
Soft deletes allow developers and admins to safely remove documents without losing data immediately. This enables workflows like reversible deletions, trash views, and auditing—while preserving compatibility with drafts, autosave, and version history.
How?
Backend
trash: true
config option to collections.deletedAt
timestamp is conditionally injected into the schema.deletedAt
instead of removing the document from the database.find
,findByID
,update
,delete
,versions
, etc.) to support a newtrash
param:trash: false
→ excludes trashed documents (default)trash: true
→ includes both trashed and non-trashed documentstrash: true
with awhere
clause like{ deletedAt: { exists: true } }
Admin Panel
/collections/:collectionSlug/trash
trash: true
is set.deletedAt
timestamp.Notes
Screen.Recording.2025-07-08.at.11.56.19.AM.mov